'''
Created on 2014/03/21

@author: phuvieng
'''
# Aloha.py, Python simulation example: a form of slotted ALOHA

# here we will look finite time, finding the probability that there are
# k active nodes at the end of epoch m

# usage: python Aloha.py s p q m k

import random, sys

class node:  
#     s = int(sys.argv[1]) 
#     p = float(sys.argv[2])  
#     q = float(sys.argv[3])
    s = 10  # number of nodes
    p = 0.5  # transmit probability
    q = 0.5  # msg creation probability
    activeset = []  # which nodes are active now
    inactiveset = []  # which nodes are inactive now
    r = random.Random(98765)
    def __init__(self): 
        # start this node in inactive mode
        node.inactiveset.append(self)
    # class (i.e. not instance) methods
    def checkgoactive():  # determine which nodes will go active
        for n in node.inactiveset:
            if node.r.uniform(0, 1) < node.q:
                node.inactiveset.remove(n)
                node.activeset.append(n)
    checkgoactive = staticmethod(checkgoactive)
    def trysent():
        numnodestried = 0  # number of nodes which have tried to send during the current epoch
        whotried = None  # which node tried to send (last) 
        # determine which nodes try to send
        for n in node.activeset:
            if node.r.uniform(0, 1) < node.p:
                whotried = n
                numnodestried += 1
        # we'll have a successful transmission if and only if exactly one node has tried to send
        if numnodestried == 1:
            node.activeset.remove(whotried)
            node.inactiveset.append(whotried)                                   
    trysent = staticmethod(trysent)
    def reset():  # resets variables after a repetition of the experiment
        for n in node.activeset:
            node.activeset.remove(n)
            node.inactiveset.append(n)
    reset = staticmethod(reset)
def main():
#     m = int(sys.argv[4])
#     k = int(sys.argv[5])
    m = 5
    k = 2
    # set up the s nodes
    for i in range(node.s): node()
    count = 0
    for rep in range(1000):
        # run the process for m epochs
        for epoch in range(m):
            node.checkgoactive()
            node.trysent()
        # len() gives the length of an object
        if len(node.activeset) == k:count += 1
        node.reset()
    print 'P(k active at time m) =', count / 1000.0
# technical device to make debugging easier, etc.
if __name__ == '__main__' : main()
